﻿using System;
using System.Collections.Generic;
using System.Text;

namespace AMS.DataAccess
{
    /// <summary>
    /// 标注的基类
    /// </summary>
    public class DBAttributes : Attribute
    {
    }

    /// <summary>
    /// 表示与一个业务对象映射的数据库表
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class DBTableAttribute : DBAttributes
    {
        /// <summary>
        /// 表示与一个业务对象映射的数据库表
        /// </summary>
        /// <param name="table"></param>
        public DBTableAttribute(string table)
        {
            this.table = table;
        }

        /// <summary>
        /// 表示与一个业务对象映射的数据库表
        /// </summary>
        public DBTableAttribute()
        {
        }

        string table;

        /// <summary>
        /// 获取保存的表名
        /// </summary>
        public string TableName
        {
            get { return table; }
        }
    }

    /// <summary>
    /// 与业务对象的属性映射的数据库列
    /// </summary>
    [AttributeUsage(AttributeTargets.Property)]
    public class DBColumnAttribute : DBAttributes
    {
        /// <summary>
        /// 与业务对象的属性映射的数据库列
        /// </summary>
        public DBColumnAttribute()
            : this(null)
        {
        }

        /// <summary>
        /// 与业务对象的属性映射的数据库列
        /// </summary>
        /// <param name="column"></param>
        public DBColumnAttribute(string column)
            : this(column, false, false)
        {
        }

        /// <summary>
        /// 与业务对象的属性映射的数据库列
        /// </summary>
        /// <param name="column">映射的列名</param>
        /// <param name="ignoreWhenInsert">表示在插入时是否忽略本字段</param>
        /// <param name="ignoreWhenUpdate">表示在更新时是否忽略本字段</param>
        public DBColumnAttribute(string column, bool ignoreWhenInsert, bool ignoreWhenUpdate)
        {
            this.column = column;
            this.ignoreUpdate = ignoreWhenUpdate;
            this.ignoreInsert = ignoreWhenInsert;
        }

        /// <summary>
        /// 与业务对象的属性映射的数据库列
        /// </summary>
        /// <param name="column">映射的列名</param>
        /// <param name="nullValue">指定与空值相等的值，在解析时将空值与NULL等同</param>
        public DBColumnAttribute(string column, object nullValue)
            : this(column, false, false)
        {
            this.nullValue = nullValue;
        }

        /// <summary>
        /// 与业务对象的属性映射的数据库列
        /// </summary>
        /// <param name="column">映射的列名</param>
        /// <param name="nullValue">指定与空值相等的值，在解析时将空值与NULL等同</param>
        /// <param name="ignoreWhenInsert">表示在插入时是否忽略本字段</param>
        /// <param name="ignoreWhenUpdate">表示在更新时是否忽略本字段</param>
        public DBColumnAttribute(string column, object nullValue, bool ignoreWhenInsert, bool ignoreWhenUpdate)
            : this(column, ignoreWhenInsert, ignoreWhenUpdate)
        {
            this.nullValue = nullValue;
        }

        /// <summary>
        /// 列名。可空，如果为空，则在处理上应该取属性名
        /// </summary>
        private string column;

        /// <summary>
        /// 在构造Insert语句的时候是否忽略这个字段
        /// </summary>
        private bool ignoreInsert;

        /// <summary>
        /// 在构造Update语句的时候是否忽略这个字段
        /// </summary>
        private bool ignoreUpdate;

        /// <summary>
        /// 表示空值的值
        /// </summary>
        private object nullValue;

        /// <summary>
        /// 获取列名
        /// </summary>
        public string Column
        {
            get { return column; }
        }

        /// <summary>
        /// 获取或设置在构造 Insert 语句的时候是否忽略这个字段
        /// </summary>
        public bool IgnoreInsert
        {
            get { return ignoreInsert; }
            set { ignoreInsert = value; }
        }

        /// <summary>
        /// 获取或设置在构造 update 语句的时候是否忽略这个字段
        /// </summary>
        public bool IgnoreUpdate
        {
            get { return ignoreUpdate; }
            set { ignoreInsert = value; }
        }

        /// <summary>
        /// 获取表示空值的值
        /// </summary>
        public object NullValue
        {
            get { return nullValue; }
        }
    }

    /// <summary>
    /// 表示与映射的列是数据库表的主键
    /// </summary>
    [AttributeUsage(AttributeTargets.Property)]
    public class DBPrimaryKeyColumnAttribute : DBColumnAttribute
    {
        /// <summary>
        /// 表示与映射的列是数据库表的主键
        /// </summary>
        public DBPrimaryKeyColumnAttribute()
            : this(null)
        {
        }

        /// <summary>
        /// 表示与映射的列是数据库表的主键
        /// </summary>
        /// <param name="column"></param>
        public DBPrimaryKeyColumnAttribute(string column)
            : this(column, false)
        {
        }

        /// <summary>
        /// 表示与映射的列是数据库表的主键
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="isIdentity">指定表列是否为数据库自动填充值。如果为数据库自动填充值，在插入的更新时将忽略这个字段。</param>
        public DBPrimaryKeyColumnAttribute(string column, bool isIdentity)
            : this(column, isIdentity, isIdentity)
        {
        }

        /// <summary>
        /// 表示与映射的列是数据库表的主键
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="isIdentity">是否在数据库中的一个自增长字段</param>
        /// <param name="ignoreWhenInsert">在构造 insert 语句时是否忽略此属性</param>
        public DBPrimaryKeyColumnAttribute(string column, bool isIdentity, bool ignoreWhenInsert)
            : base(column, ignoreWhenInsert, true)
        {
            this.isIdentity = isIdentity;
        }

        /// <summary>
        /// 是否自增长列
        /// </summary>
        private bool isIdentity;

        /// <summary>
        /// 获取一个值，表示这个列是否自增长列
        /// </summary>
        public bool IsIdentity
        {
            get { return isIdentity; }
        }
    }

    /// <summary>
    /// 表示该列是一个外键列
    /// </summary>
    public class DBForignKeyColumnAttribute : DBColumnAttribute
    {
        /// <summary>
        /// 表示该列是一个外键列
        /// </summary>
        /// <param name="parentTableName"></param>
        public DBForignKeyColumnAttribute(string parentTableName)
            : this(null, parentTableName)
        {
        }

        /// <summary>
        /// 表示该列是一个外键列
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="parentTableName">被引用的表名</param>
        public DBForignKeyColumnAttribute(string column, string parentTableName)
            : base(column)
        {
            refTableName = parentTableName;
        }

        /// <summary>
        /// 被引用的表名
        /// </summary>
        private string refTableName;

        /// <summary>
        /// 获取被引用的表名
        /// </summary>
        public string ParentTableName
        {
            get { return refTableName; }
        }
    }

    /// <summary>
    /// 表示字段与一个时间列对应
    /// </summary>
    public class DBDateTimeAttribute : DBColumnAttribute
    {
        /// <summary>
        /// 表示字段与一个时间列对应
        /// </summary>
        public DBDateTimeAttribute()
            : this(null)
        {
        }

        /// <summary>
        /// 表示字段与一个时间列对应
        /// </summary>
        /// <param name="column">列名</param>
        public DBDateTimeAttribute(string column)
            : this(column, DateTimeType.DateTime, false, false)
        {
        }

        /// <summary>
        /// 表示日期时间类型。实际是指是否包括时间
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="dtType">日期时间类型</param>
        public DBDateTimeAttribute(string column, DateTimeType dtType)
            : this(column, dtType, false, false)
        {
        }

        /// <summary>
        /// 表示字段与一个时间列对应
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="dtType">日期时间类型</param>
        /// <param name="ignoreWhenInsert">在构造 insert 语句时是否忽略</param>
        /// <param name="ignoreWhenUpdate">在构造 upate 语句时是否忽略</param>
        public DBDateTimeAttribute(string column, DateTimeType dtType, bool ignoreWhenInsert, bool ignoreWhenUpdate)
            : base(column, ignoreWhenInsert, ignoreWhenUpdate)
        {
        }

        /// <summary>
        /// 日期时间类型
        /// </summary>
        private DateTimeType dateTimeType = DateTimeType.DateTime;

        /// <summary>
        /// 获取日期时间类型，默认的类型是包括日期和时间信息
        /// </summary>
        public DateTimeType DateTimeType
        {
            get { return dateTimeType; }
        }
    }

    /// <summary>
    /// 表示与属性对应的数据库列在表现上为一个枚举类型
    /// </summary>
    public class DBEnumColumnAttribute : DBColumnAttribute
    {
        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        public DBEnumColumnAttribute()
            : this(null)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        public DBEnumColumnAttribute(string column)
            : this(column, false, false)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="ignoreWhenInsert">在构造 insert 语句时是否忽略</param>
        /// <param name="ignoreWhenUpdate">在构造 upate 语句时是否忽略</param>
        public DBEnumColumnAttribute(string column, bool ignoreWhenInsert, bool ignoreWhenUpdate)
            : base(column, ignoreWhenInsert, ignoreWhenUpdate)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="defaultValue">默认值</param>
        public DBEnumColumnAttribute(string column, object defaultValue)
            : this(column, defaultValue, false, false)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="ignoreWhenInsert">在构造 insert 语句时是否忽略</param>
        /// <param name="ignoreWhenUpdate">在构造 upate 语句时是否忽略</param>
        public DBEnumColumnAttribute(string column, object defaultValue, bool ignoreWhenInsert, bool ignoreWhenUpdate)
            : base(column, defaultValue, ignoreWhenInsert, ignoreWhenUpdate)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="enumType">枚举类型</param>
        public DBEnumColumnAttribute(string column, Type enumType)
            : this(column, enumType, false, false)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="enumType">枚举类型</param>
        /// <param name="ignoreWhenInsert">在构造 insert 语句时是否忽略</param>
        /// <param name="ignoreWhenUpdate">在构造 upate 语句时是否忽略</param>
        public DBEnumColumnAttribute(string column, Type enumType, bool ignoreWhenInsert, bool ignoreWhenUpdate)
            : base(column, ignoreWhenInsert, ignoreWhenUpdate)
        {
            this.enumType = enumType;
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="enumType">枚举类型</param>
        /// <param name="defaultValue">默认值</param>
        public DBEnumColumnAttribute(string column, Type enumType, object defaultValue)
            : this(column, enumType, defaultValue, false, false)
        {
        }

        /// <summary>
        /// 表示与属性对应的数据库列在表现上为一个枚举类型
        /// </summary>
        /// <param name="column">列名</param>
        /// <param name="enumType">枚举类型</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="ignoreWhenInsert">在构造 insert 语句时是否忽略</param>
        /// <param name="ignoreWhenUpdate">在构造 upate 语句时是否忽略</param>
        public DBEnumColumnAttribute(string column, Type enumType, object defaultValue, bool ignoreWhenInsert, bool ignoreWhenUpdate)
            : base(column, defaultValue, ignoreWhenInsert, ignoreWhenUpdate)
        {
            this.enumType = enumType;
        }

        /// <summary>
        /// 枚举类型
        /// </summary>
        private Type enumType;

        /// <summary>
        /// 获取枚举类型
        /// </summary>
        public Type EnumType
        {
            get { return enumType; }
        }
    }

    /// <summary>
    /// 表示一个版本号字段。版本号字段用来控制业务对象的更新
    /// </summary>
    public class DBVersionColumnAttribute : DBColumnAttribute
    {
        /// <summary>
        /// 表示一个版本号字段。版本号字段用来控制业务对象的更新
        /// </summary>
        public DBVersionColumnAttribute()
            : this(null)
        {
        }

        /// <summary>
        /// 表示一个版本号字段。版本号字段用来控制业务对象的更新
        /// </summary>
        /// <param name="column"></param>
        public DBVersionColumnAttribute(string column)
            : base(column, true, true)
        {
        }
    }

    /// <summary>
    /// 表示一个显示字段，这个字段在Insert和Update时不会被解析
    /// </summary>
    [AttributeUsage(AttributeTargets.Property)]
    public class DBDisplayColumnAttribute : DBColumnAttribute
    {
        /// <summary>
        /// 表示一个显示字段，这个字段在Insert和Update时不会被解析
        /// </summary>
        public DBDisplayColumnAttribute()
            : this(null)
        {
        }

        /// <summary>
        /// 表示一个显示字段，这个字段在Insert和Update时不会被解析
        /// </summary>
        /// <param name="column">列名</param>
        public DBDisplayColumnAttribute(string column)
            : base(column, true, true)
        {
        }
    }
}
